#lang racket


(require "../ast/main.rkt")

(provide generic-backend%)


(define (null-fn sym . args)
  (error sym "You must choose a backend; shapes will not be created."))

(define-syntax define-null-method
  (syntax-rules ()
    ((_ (name arg ...))
     (define/public (name arg ...)
       (null-fn 'name arg ...)))))

(define-syntax define-null-methods
  (syntax-rules ()
    ((_ name ...)
     (begin
       (define/public (name . args)
         (null-fn 'name args)) ...))))


(define generic-backend%
  (class* object% ()
    (super-new)
    
    
    ; evaluate
    
    ; node -> shape
    (define-null-method (evaluate-node node))
    
    ; any -> any
    (define/public (evaluate expr)
      (cond ((pair? expr)
             (cons
              (send this evaluate (car expr))
              (send this evaluate (cdr expr))))
            ((is-a? expr node%)
             (send this evaluate-node expr))
            (else
             expr)))
    
    ; any -> any
    (define/public (evaluate-toplevel expr)
      (send this evaluate expr))
    
    
    (define-null-methods
      ; shapes
      bbox
      
      ; points
      point
      
      point?
      
      point-c
      
      ; lines
      arc
      elliptical-arc
      ellipse
      line
      nurbs-curve
      spline
      
      line?
      line-closed?
      polygonal-line?
      
      line-begin-c
      line-cs
      line-end-c
      
      ; surfaces
      donut
      ngon
      nurbs-surface
      star
      surface
      
      surface?
      
      surface-curvature
      surface-domain
      
      ; solids
      box
      cone
      cone-frustum
      cylinder
      pyramid
      sphere
      
      solid?
      
      ; generic shapes
      circle
      rectangle
      
      ; text
      text
      
      ; transformations 
      extrude
      intersect
      join
      loft
      move
      offset
      rotate
      scale
      section
      slice
      subtract
      sweep
      thicken
      union
      
      ; lang
      align
      parametric
      lift
      on
      par
      
      ; cad
      clone-shape
      clone-shapes
      delete-shape
      delete-shapes
      get-shapes
      layer
      prompt-point
      prompt-shape
      render-shapes
      select-shape
      select-shapes
      unselect-all-shapes
      view
      valid-shape?)))